package com.ruoyi.api.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.api.api.RedisKeyExpirationCallback;
import com.ruoyi.api.api.RedisKeyExpirationMonitor;
import com.ruoyi.api.api.RedisStockService;
import com.ruoyi.api.domain.*;
import com.ruoyi.api.mapper.*;
import com.ruoyi.api.service.IOrderService;
import com.ruoyi.api.vo.OrderVo;
import com.ruoyi.api.vo.ProductVo;
import com.ruoyi.api.vo.UserAddressVo;
import com.ruoyi.common.constant.OrderStatusConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author 寻觅
 * @since 2025-06-04
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    @Autowired
    OrderMapper orderMapper;

    @Autowired
    MerchantMapper merchantMapper;

    @Autowired
    ProductsMapper productsMapper;

    @Autowired
    DictRegionMapper dictRegionMapper;

    @Autowired
    RedisCache redisCache;

    @Autowired
    RedissonClient redissonClient;

    @Autowired
    ShoppingCartMapper shoppingCartMapper;

    @Autowired
    RedisTemplate<String, String> redisTemplate;

    @Autowired
    UserWalletMapper userWalletMapper;


    private static final String PRODUCT_DATA = "products_data_stock";
    private static final String PRODUCT_DATA_ALL = "products_data";
    private static String ORDER_TIMEOUT_KEY;

    @Value("${spring.redis.host}")
    String getRedisHost;

    @Value("${spring.redis.port}")
    Integer getRedisPort;

    @Value("${spring.redis.database}")
    Integer getRedisDatabase;

    @Value("${spring.redis.password}")
    String getRedisPassword;

    /**
     * 创建订单
     *
     * @param
     * @return
     */
    @Override
    @Transactional
    public String createOrder(List<Integer> productIds, Integer userId) {
        if (productIds == null || productIds.isEmpty()) {
            throw new IllegalArgumentException("商品ID列表不能为空");
        }

//        LoginUser loginUser = SecurityUtils.getLoginUser();
        BigDecimal totalAmount = BigDecimal.ZERO;
        int totalNumber = 0;
        String products = null;
        Integer merchantId = null;
        String merchantName = null;
        Map<String, Integer> productIdToQuantityMap = new HashMap<>(); // 商品ID到数量的映射
        StringBuilder productQuantities = new StringBuilder(); // 存储逗号分隔的数量
        // 遍历处理每个商品，确保同一商家
        for (Integer productId : productIds) {
            // 获取购物车中的商品信息
            ShoppingCart cartItem = shoppingCartMapper.selectByUserIdAndProductId(productId , userId);

            if (cartItem == null) {
                throw new ServiceException("购物车中不存在该商品，ID: " + productId);
            }

            // 获取商品信息
            Products product = productsMapper.selectById(productId);
            if (product == null) {
                throw new ServiceException("商品不存在，ID: " + productId);
            }

            // 检查是否为同一商家
            if (merchantId == null) {
                merchantId = Math.toIntExact(product.getMerchantId());
                Merchant merchant = merchantMapper.selectById(merchantId);
                if (merchant == null) {
                    throw new ServiceException("商家不存在，ID: " + merchantId);
                }
                merchantName = merchant.getBusinessName();
            } else {
                throw new ServiceException("不能跨商家创建订单");
            }

            // 计算总金额
            totalAmount = totalAmount.add(product.getPrice().multiply(BigDecimal.valueOf(cartItem.getNumber())));
            //计算总数量
            totalNumber += cartItem.getNumber();
            // 拼接商品数量
            productQuantities.append(cartItem.getNumber()).append(",");
            // 记录商品ID和对应的购物车数量
            productIdToQuantityMap.put(productId.toString(), cartItem.getNumber());
            shoppingCartMapper.updateById(cartItem);
        }

        String finalProductQuantities = productQuantities.length() > 0 ?
                productQuantities.substring(0, productQuantities.length() - 1) :
                "";
        products = finalProductQuantities;
        RLock lock = redissonClient.getLock("order_lock:" + userId);
        boolean isLocked = false;

        try {
            isLocked = lock.tryLock(5, 30, TimeUnit.SECONDS);
            if (!isLocked) {
                throw new ServiceException("系统繁忙，请稍后重试");
            }

            // 扣减所有商品库存（使用Lua脚本）
            RedisStockService stockService = new RedisStockService(getRedisHost, getRedisPort, getRedisPassword, getRedisDatabase);
            boolean allStockDeducted = true;

            for (Map.Entry<String, Integer> entry : productIdToQuantityMap.entrySet()) {
                String productId = entry.getKey();
                Integer quantity = entry.getValue();

                boolean stockDeducted = stockService.deductStock(
                        productId,
                        quantity
                );

                if (!Boolean.TRUE.equals(stockDeducted)) {
                    allStockDeducted = false;
                    break;
                }
            }

            if (!allStockDeducted) {
                // 回滚已扣减的库存
                for (Map.Entry<String, Integer> entry : productIdToQuantityMap.entrySet()) {
                    String productId = entry.getKey();
                    Integer quantity = entry.getValue();
                    stockService.addStock(productId, quantity);
                }
                throw new ServiceException("库存不足，无法创建订单");
            }
            stockService.close();

            // 创建主订单
            Order mainOrder = new Order();
            mainOrder.setOrderStatus(OrderStatusConstants.PENDING_PAYMENT);
            mainOrder.setCreateTime(LocalDateTime.now());
            mainOrder.setExpireTime(LocalDateTime.now().plusMinutes(30));
            mainOrder.setUserId(Long.valueOf(userId));
            mainOrder.setUserName("张三 ");
            mainOrder.setMerchantId(merchantId);
            mainOrder.setMerchantName(merchantName);
            String joinedProductIds = productIds.stream().map(String::valueOf).collect(Collectors.joining(","));
            mainOrder.setProductId(joinedProductIds);
            mainOrder.setProductQuantity(totalNumber);
            mainOrder.setProductSubtotal(totalAmount);
            mainOrder.setProductQuantityOne(products);

            // 插入主订单
            int rows = orderMapper.insert(mainOrder);
            if (rows != 1) {
                // 回滚Redis库存
                for (Map.Entry<String, Integer> entry : productIdToQuantityMap.entrySet()) {
                    String productId = entry.getKey();
                    Integer quantity = entry.getValue();
                    redisTemplate.opsForHash().increment(PRODUCT_DATA, productId, quantity);
                }
                throw new ServiceException("订单创建失败");
            }

            // 设置订单超时Key（用于自动释放库存）
            String orderTimeoutKey = mainOrder.getOrderId() + "-" + joinedProductIds;
            redisCache.setCacheObject(
                    orderTimeoutKey,
                    productIdToQuantityMap, // 缓存商品ID到数量的映射
                    180,
                    TimeUnit.SECONDS
            );
            // 监控订单超时
            setupOrderExpirationMonitor(mainOrder.getOrderId(), orderTimeoutKey, productIdToQuantityMap);
            return mainOrder.getOrderId();

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new ServiceException("操作被中断");
        } finally {
            if (isLocked && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    private void setupOrderExpirationMonitor(String orderId, String timeoutKey, Map<String, Integer> integerIntegerMap) {
        System.out.println("他的key是+===============================:" + timeoutKey);
        RedisKeyExpirationMonitor monitor = new RedisKeyExpirationMonitor();
        monitor.redisKeyExpirationMonitor(timeoutKey,
                getRedisHost, // 确保为方法调用，添加括号
                getRedisPort,
                getRedisPassword,
                getRedisDatabase,
                new RedisKeyExpirationCallback() {
                    @Override
                    public void onKeyExpired(String expiredKey) {

                        System.out.println("商品id是：：：：：：：和商品数据是：：：：" + integerIntegerMap);

                        if (orderId == null) {
                            System.out.println("无法从过期Key中解析订单ID");
                            return;
                        }

                        // 查询订单
                        Order order = orderMapper.selectById(orderId);
                        System.out.println("查询订单结果：orderId=" + orderId + ", order=" + order);

                        if (order != null && OrderStatusConstants.PENDING_PAYMENT == order.getOrderStatus()) {
                            // 更新订单状态
                            order.setOrderStatus(OrderStatusConstants.CANCELLED);
                            order.setUpdateTime(LocalDateTime.now());
                            int updateResult = orderMapper.updateById(order);
                            System.out.println("数据库更新结果：updateResult=" + updateResult);

                            if (updateResult == 1) {
                                System.out.println("开始恢复 Redis 库存");

                                if (redisCache != null) {
                                    Map<String, Integer> productIdToQuantityMap = redisCache.getCacheMap(timeoutKey);

                                    System.out.println("啊u后未断奶阿文i都把我丢吧" + productIdToQuantityMap);
                                    if (productIdToQuantityMap != null && !integerIntegerMap.isEmpty()) {
                                        System.out.println("获取到商品数量映射，大小: " + productIdToQuantityMap.size());
                                        RedisStockService stockService = new RedisStockService(
                                                getRedisHost,
                                                getRedisPort,
                                                getRedisPassword,
                                                getRedisDatabase
                                        );
                                        System.out.println("开始恢复数据======================================================================");
                                        for (Map.Entry<String, Integer> entry : integerIntegerMap.entrySet()) {
                                            String productId = entry.getKey();
                                            Integer quantity = entry.getValue();
                                            System.out.println("恢复数据种======================================================================");
                                            System.out.println(quantity + "数量======================================================================");
                                            System.out.println(productId + "ID======================================================================");
                                            if (productId != null && quantity > 0) {
                                                // 使用正确的 Redis 键名恢复库存
                                                boolean success = stockService.hincrByStock(PRODUCT_DATA, productId, quantity);
                                                System.out.println("awdiaouwndiawundawiod" + productId);
                                                System.out.println("安备好发部位覅挎包我 " + quantity);
                                                if (success) {
                                                    System.out.println("恢复成功，productId=" + productId + ", 数量=" + quantity);
                                                } else {
                                                    System.out.println("恢复失败，productId=" + productId + ", 数量=" + quantity);
                                                }
                                            }
                                        }

                                        stockService.close();
                                        System.out.println("已关闭================================================");
                                    } else {
                                        System.out.println("商品数量映射为空或不存在，Key=" + productIdToQuantityMap);
                                    }
                                } else {
                                    System.out.println("redisCache 未初始化");
                                }
                            } else {
                                System.out.println("订单状态更新失败");
                            }
                        } else {
                            System.out.println("订单不存在或状态异常");
                        }
                    }
                });
    }

    /**
     * 支付订单
     *
     * @param
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String payOrder(Order order) {
        // 1. 更新订单状态/更新钱包数据
        Order orderToUpdate = updateOrderStatus(order);
        // 2. 更新商品销量并同步缓存
        updateProductSales(orderToUpdate.getProductId(), orderToUpdate.getOrderId());
        // 3. 同步商品数据到缓存
        syncProductsToCache();
        return order.getOrderId();
    }

    /**
     * 更新订单状态
     */
    private Order updateOrderStatus(Order order) {
        Order existingOrder = orderMapper.selectById(order.getOrderId());

        if (existingOrder == null) {
            System.out.println("订单不存在, 订单ID: " + order.getOrderId());
            throw new RuntimeException("订单不存在");
        }
        UserWallet userWallet = userWalletMapper.selectByIdUser(existingOrder.getUserId(), order.getPaymentType());
        // 扣除钱包余额
        BigDecimal walletAmount = userWallet.getAmount();
        BigDecimal orderAmount = existingOrder.getProductSubtotal();
        if (walletAmount.compareTo(orderAmount) < 0) {
            throw new RuntimeException("余额不足");
        }
        BigDecimal newAmount = walletAmount.subtract(orderAmount);
        newAmount = newAmount.setScale(2, RoundingMode.HALF_UP);
        userWallet.setAmount(newAmount);
        userWalletMapper.updateById(userWallet);
        // 跟新订单状态
        existingOrder.setPaymentType(order.getPaymentType());
        existingOrder.setPaymentTime(LocalDateTime.now());
        existingOrder.setOrderStatus(OrderStatusConstants.PAID);

        int result = orderMapper.updateById(existingOrder);
        if (result <= 0) {
            System.out.println("订单状态更新失败, 订单ID: " + order.getOrderId());
            throw new RuntimeException("订单状态更新失败");
        }

        System.out.println("订单状态更新成功, 订单ID: " + order.getOrderId());
        return existingOrder;
    }

    /**
     * 更新商品销量
     */
    private void updateProductSales(String productIds, String orderId) {
        String[] productIdArray = productIds.split(",");
        List<Products> productsToUpdate = new ArrayList<>();

        // 收集需要更新的商品信息
        for (String productId : productIdArray) {
            Integer saleCount = redisCache.getCacheMapValue(PRODUCT_DATA, productId);
            if (saleCount == null) {
                System.out.println("商品销量缓存不存在, 商品ID: , 订单ID: " + productId + orderId);
                continue;
            }
            Products product = productsMapper.selectById(productId);
            if (product == null) {
                System.out.println("商品不存在, 商品ID: , 订单ID: " + productId + orderId);
                continue;
            }

            product.setSaleCount(saleCount);
            productsToUpdate.add(product);
        }
        if (!CollectionUtils.isEmpty(productsToUpdate)) {
            for (Products product : productsToUpdate) {
                productsMapper.updateById(product);
                System.out.println("商品销量更新成功, 商品ID: 订单ID: " + product.getId() + orderId);
            }
        }
    }

    /**
     * 同步商品数据到缓存
     */
    private void syncProductsToCache() {
        List<Products> allProducts = productsMapper.selectList(null);
        if (CollectionUtils.isEmpty(allProducts)) {
            System.out.println("没有找到任何商品数据");
            return;
        }
        redisCache.deleteObject(PRODUCT_DATA_ALL);
        for (Products product : allProducts) {
            redisCache.setCacheMapValue(PRODUCT_DATA_ALL, product.getId().toString(), product);
        }

        System.out.println("商品数据已同步到缓存, 条记录" + allProducts.size());
    }

    /**
     * 订单详细
     *
     * @param orderId
     * @return
     */
    @Override
    public OrderVo info(String orderId) {
        OrderVo orderVo = new OrderVo();

        // 订单信息
        Order order = orderMapper.selectById(orderId);
        if (order == null) {
            return orderVo; // 返回空对象而非null
        }

        // 设置订单基本信息
        orderVo.setOrderId(order.getOrderId());
        orderVo.setStatus(order.getOrderStatus());
        orderVo.setCreatedAt(order.getCreateTime());
        orderVo.setTotalPrice(order.getProductSubtotal());
        orderVo.setTotalNumber(order.getProductQuantity());
        orderVo.setShippingFee(BigDecimal.ZERO);

        // 商品信息处理
        List<ProductVo> productVos = new ArrayList<>();

        if (order.getProductId() != null && !order.getProductId().isEmpty()
                && order.getProductQuantityOne() != null && !order.getProductQuantityOne().isEmpty()) {

            String[] productIds = order.getProductId().split(",");
            String[] quantities = order.getProductQuantityOne().split(",");

            if (productIds.length == quantities.length) {
                for (int i = 0; i < productIds.length; i++) {
                    try {
                        String productId = productIds[i];
                        String quantityStr = quantities[i];

                        ProductVo product = productsMapper.ById(Integer.valueOf(productId));
                        if (product != null) {
                            product.setQuantity(Integer.parseInt(quantityStr));
                            productVos.add(product);
                        }
                    } catch (NumberFormatException e) {
                        System.out.println("无效的商品ID或数量格式" + productIds[i] + quantities[i] + e);
                    }
                }
            } else {
                System.out.println("商品ID数量与商品数量不匹配" +
                        Arrays.toString(productIds) + Arrays.toString(quantities));
            }
        }
        orderVo.setProductVo(productVos);

        // 地址信息

        if (order.getAddressId() != null) {
            UserAddressVo addressVo = dictRegionMapper.getById(order.getAddressId());
            if (addressVo != null) {
                // 构建完整地址
                String fullAddress = String.join(" ",
                        Optional.ofNullable(addressVo.getLevelOneName()).orElse(""),
                        Optional.ofNullable(addressVo.getLevelTwoName()).orElse(""),
                        Optional.ofNullable(addressVo.getLevelThreeName()).orElse(""),
                        Optional.ofNullable(addressVo.getLevelFourName()).orElse(""),
                        Optional.ofNullable(addressVo.getAddress()).orElse("")
                ).trim();

                addressVo.setAddress(fullAddress);
                orderVo.setShippingAddress(addressVo);
            }
        }

        return orderVo;
    }

    /**
     * 订单列表
     *
     * @param
     * @return
     */
    @Override
    public List<OrderVo> listData() {

        List<Order> orders = orderMapper.selectList(null);
        if (orders == null || orders.isEmpty()) {
            return Collections.emptyList();
        }
        Map<Integer, ProductVo> productCache = new HashMap<>();
        Map<Integer, UserAddressVo> addressCache = new HashMap<>();
        return orders.stream()
                .map(order -> convertToOrderVo(order, productCache, addressCache))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    private OrderVo convertToOrderVo(Order order,
                                     Map<Integer, ProductVo> productCache,
                                     Map<Integer, UserAddressVo> addressCache) {
        OrderVo orderVo = new OrderVo();

        // 设置订单基本信息
        orderVo.setOrderId(order.getOrderId());
        orderVo.setStatus(order.getOrderStatus());
        orderVo.setCreatedAt(order.getCreateTime());
        orderVo.setTotalPrice(order.getProductSubtotal());
        orderVo.setTotalNumber(order.getProductQuantity());
        orderVo.setMerchantName(order.getMerchantName());
        orderVo.setShippingFee(BigDecimal.ZERO);

        // 处理商品信息
        List<ProductVo> productVos = processProductInfo(order, productCache);
        orderVo.setProductVo(productVos);

        // 处理地址信息
        UserAddressVo addressVo = processAddressInfo(order, addressCache);
        orderVo.setShippingAddress(addressVo);

        return orderVo;
    }

    private List<ProductVo> processProductInfo(Order order, Map<Integer, ProductVo> productCache) {
        List<ProductVo> productVos = new ArrayList<>();

        if (order.getProductId() == null || order.getProductId().isEmpty() ||
                order.getProductQuantityOne() == null || order.getProductQuantityOne().isEmpty()) {
            return productVos;
        }

        String[] productIds = order.getProductId().split(",");
        String[] quantities = order.getProductQuantityOne().split(",");

        if (productIds.length != quantities.length) {
            System.out.println("商品ID数量与商品数量不匹配" +
                    order.getOrderId() + Arrays.toString(productIds) + Arrays.toString(quantities));
            return productVos;
        }

        for (int i = 0; i < productIds.length; i++) {
            try {
                int productId = Integer.parseInt(productIds[i]);
                int quantity = Integer.parseInt(quantities[i]);

                ProductVo product = productCache.computeIfAbsent(productId,
                        id -> productsMapper.ById(id));

                if (product != null) {
                    product.setQuantity(quantity);
                    productVos.add(product);
                } else {
                    System.out.println("商品不存在" + order.getOrderId() + productId);
                }
            } catch (NumberFormatException e) {
                System.out.println("无效的商品ID或数量格式" +
                        order.getOrderId() + productIds[i] + quantities[i] + e);
            }
        }

        return productVos;
    }

    private UserAddressVo processAddressInfo(Order order, Map<Integer, UserAddressVo> addressCache) {
        if (order.getAddressId() == null) {
            return null;
        }
        return addressCache.computeIfAbsent(order.getAddressId(), id -> {
            UserAddressVo addressVo = dictRegionMapper.getById(id);
            if (addressVo != null) {
                String fullAddress = Stream.of(
                                addressVo.getLevelOneName(),
                                addressVo.getLevelTwoName(),
                                addressVo.getLevelThreeName(),
                                addressVo.getLevelFourName(),
                                addressVo.getAddress())
                        .filter(Objects::nonNull)
                        .collect(Collectors.joining(" "))
                        .trim();

                addressVo.setAddress(fullAddress);
            }
            return addressVo;
        });
    }

    /**
     * 取消订单
     *
     * @param orderId
     * @return
     */
    @Override
    public String cancelOrder(String orderId) {
        Order order = orderMapper.selectById(orderId);
        order.setOrderStatus(OrderStatusConstants.CANCELLED);
        orderMapper.updateById(order);
        Integer cacheMapValue = redisCache.getCacheMapValue(PRODUCT_DATA, order.getProductId());
        redisCache.setCacheMapValue(PRODUCT_DATA, order.getOrderId(), cacheMapValue + order.getProductQuantity());
        redisCache.deleteObject(ORDER_TIMEOUT_KEY);
        return orderId;
    }

    /**
     * 修改订单地址和支付方式
     *
     * @param
     * @return
     */
    @Override
    public Integer editAddress(String id, Integer addressId, Integer payType) {
        Order order = orderMapper.selectById(id);
        order.setAddressId(addressId);
        order.setPaymentType(payType);
        return orderMapper.updateById(order);
    }
}
